home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Common / include / asyncio.h next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  7.5 KB  |  272 lines

  1. //------------------------------------------------------------------------------
  2. // File: AsyncIo.h
  3. //
  4. // Desc: DirectShow sample code - base library for I/O functionality.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #ifndef __ASYNCIO_H__
  11. #define __ASYNCIO_H__
  12. //
  13. // definition of CAsyncFile object that performs file access. It provides
  14. // asynchronous, unbuffered, aligned reads from a file, using a worker thread
  15. // on win95 and potentially overlapped i/o if available.
  16.  
  17. // !!! Need to use real overlapped i/o if available
  18. // currently only uses worker thread, not overlapped i/o
  19.  
  20.  
  21. class CAsyncIo;
  22. class CAsyncStream;
  23.  
  24. //
  25. //  Model the stream we read from based on a file-like interface
  26. //
  27. class CAsyncStream
  28. {
  29. public:
  30.     virtual ~CAsyncStream() {};
  31.     virtual HRESULT SetPointer(LONGLONG llPos) = 0;
  32.     virtual HRESULT Read(PBYTE pbBuffer,
  33.                          DWORD dwBytesToRead,
  34.                          BOOL bAlign,
  35.                          LPDWORD pdwBytesRead) = 0;
  36.     virtual LONGLONG Size(LONGLONG *pSizeAvailable = NULL) = 0;
  37.     virtual DWORD Alignment() = 0;
  38.     virtual void Lock() = 0;
  39.     virtual void Unlock() = 0;
  40.     //virtual void SetStopHandle(HANDLE hevStop) {}
  41. };
  42.  
  43. // represents a single request and performs the i/o. Can be called on either
  44. // worker thread or app thread, but must hold pcsFile across file accesses.
  45. // (ie across SetFilePointer/ReadFile pairs)
  46. class CAsyncRequest
  47. {
  48.     CAsyncIo *m_pIo;
  49.     CAsyncStream *m_pStream;
  50.     LONGLONG      m_llPos;
  51.     BOOL        m_bAligned;
  52.     LONG     m_lLength;
  53.     BYTE*     m_pBuffer;
  54.     LPVOID     m_pContext;
  55.     DWORD    m_dwUser;
  56.     HRESULT     m_hr;
  57.  
  58. public:
  59.     // init the params for this request. Issue the i/o
  60.     // if overlapped i/o is possible.
  61.     HRESULT Request(
  62.         CAsyncIo *pIo,
  63.         CAsyncStream *pStream,
  64.         LONGLONG llPos,
  65.     LONG lLength,
  66.         BOOL bAligned,
  67.     BYTE* pBuffer,
  68.     LPVOID pContext,    // filter's context
  69.     DWORD dwUser);        // downstream filter's context
  70.  
  71.     // issue the i/o if not overlapped, and block until i/o complete.
  72.     // returns error code of file i/o
  73.     HRESULT Complete();
  74.  
  75.     // cancels the i/o. blocks until i/o is no longer pending
  76.     HRESULT Cancel()
  77.     {
  78.     return S_OK;
  79.     };
  80.  
  81.     // accessor functions
  82.     LPVOID GetContext()
  83.     {
  84.         return m_pContext;
  85.     };
  86.  
  87.     DWORD GetUser()
  88.     {
  89.     return m_dwUser;
  90.     };
  91.  
  92.     HRESULT GetHResult() {
  93.         return m_hr;
  94.     };
  95.  
  96.     // we set m_lLength to the actual length
  97.     LONG GetActualLength() {
  98.         return m_lLength;
  99.     };
  100.  
  101.     LONGLONG GetStart() {
  102.         return m_llPos;
  103.     };
  104. };
  105.  
  106.  
  107. typedef CGenericList<CAsyncRequest> CRequestList;
  108.  
  109. // this class needs a worker thread, but the ones defined in classes\base
  110. // are not suitable (they assume you have one message sent or posted per
  111. // request, whereas here for efficiency we want just to set an event when
  112. // there is work on the queue).
  113. //
  114. // we create CAsyncRequest objects and queue them on m_listWork. The worker
  115. // thread pulls them off, completes them and puts them on m_listDone.
  116. // The events m_evWork and m_evDone are set when the corresponding lists are
  117. // not empty.
  118. //
  119. // Synchronous requests are done on the caller thread. These should be
  120. // synchronised by the caller, but to make sure we hold m_csFile across
  121. // the SetFilePointer/ReadFile code.
  122. //
  123. // Flush by calling BeginFlush. This rejects all further requests (by
  124. // setting m_bFlushing within m_csLists), cancels all requests and moves them
  125. // to the done list, and sets m_evDone to ensure that no WaitForNext operations
  126. // will block. Call EndFlush to cancel this state.
  127. //
  128. // we support unaligned calls to SyncRead. This is done by opening the file
  129. // twice if we are using unbuffered i/o (m_dwAlign > 1).
  130. // !!!fix this to buffer on top of existing file handle?
  131. class CAsyncIo
  132. {
  133.  
  134.     CCritSec m_csReader;
  135.     CAsyncStream *m_pStream;
  136.  
  137.     CCritSec m_csLists;      // locks access to the list and events
  138.     BOOL m_bFlushing;        // true if between BeginFlush/EndFlush
  139.     CRequestList m_listWork;
  140.     CRequestList m_listDone;
  141.     CAMEvent m_evWork;         // set when list is not empty
  142.     CAMEvent m_evDone;
  143.  
  144.     // for correct flush behaviour: all protected by m_csLists
  145.     LONG    m_cItemsOut;    // nr of items not on listDone or listWork
  146.     BOOL    m_bWaiting;     // TRUE if someone waiting for m_evAllDone
  147.     CAMEvent m_evAllDone;   // signal when m_cItemsOut goes to 0 if m_cWaiting
  148.  
  149.  
  150.     CAMEvent m_evStop;         // set when thread should exit
  151.     HANDLE m_hThread;
  152.  
  153.     LONGLONG Size() {
  154.         ASSERT(m_pStream != NULL);
  155.         return m_pStream->Size();
  156.     };
  157.  
  158.     // start the thread
  159.     HRESULT StartThread(void);
  160.  
  161.     // stop the thread and close the handle
  162.     HRESULT CloseThread(void);
  163.  
  164.     // manage the list of requests. hold m_csLists and ensure
  165.     // that the (manual reset) event hevList is set when things on
  166.     // the list but reset when the list is empty.
  167.     // returns null if list empty
  168.     CAsyncRequest* GetWorkItem();
  169.  
  170.     // get an item from the done list
  171.     CAsyncRequest* GetDoneItem();
  172.  
  173.     // put an item on the work list
  174.     HRESULT PutWorkItem(CAsyncRequest* pRequest);
  175.  
  176.     // put an item on the done list
  177.     HRESULT PutDoneItem(CAsyncRequest* pRequest);
  178.  
  179.     // called on thread to process any active requests
  180.     void ProcessRequests(void);
  181.  
  182.     // initial static thread proc calls ThreadProc with DWORD
  183.     // param as this
  184.     static DWORD WINAPI InitialThreadProc(LPVOID pv) {
  185.     CAsyncIo * pThis = (CAsyncIo*) pv;
  186.     return pThis->ThreadProc();
  187.     };
  188.  
  189.     DWORD ThreadProc(void);
  190.  
  191. public:
  192.  
  193.     CAsyncIo(CAsyncStream *pStream);
  194.     ~CAsyncIo();
  195.  
  196.     // open the file
  197.     HRESULT Open(LPCTSTR pName);
  198.  
  199.     // ready for async activity - call this before
  200.     // calling Request
  201.     HRESULT AsyncActive(void);
  202.  
  203.     // call this when no more async activity will happen before
  204.     // the next AsyncActive call
  205.     HRESULT AsyncInactive(void);
  206.  
  207.     // queue a requested read. must be aligned.
  208.     HRESULT Request(
  209.             LONGLONG llPos,
  210.         LONG lLength,
  211.                 BOOL bAligned,
  212.         BYTE* pBuffer,
  213.         LPVOID pContext,
  214.         DWORD dwUser);
  215.  
  216.     // wait for the next read to complete
  217.     HRESULT WaitForNext(
  218.             DWORD dwTimeout,
  219.         LPVOID *ppContext,
  220.         DWORD * pdwUser,
  221.                 LONG * pcbActual
  222.                 );
  223.  
  224.     // perform a read of an already aligned buffer
  225.     HRESULT SyncReadAligned(
  226.             LONGLONG llPos,
  227.         LONG lLength,
  228.         BYTE* pBuffer,
  229.                 LONG* pcbActual,
  230.                 PVOID pvContext
  231.                 );
  232.  
  233.     // perform a synchronous read. will be buffered
  234.     // if not aligned.
  235.     HRESULT SyncRead(
  236.                 LONGLONG llPos,
  237.                 LONG lLength,
  238.                 BYTE* pBuffer);
  239.  
  240.     // return length
  241.     HRESULT Length(LONGLONG *pllTotal, LONGLONG* pllAvailable);
  242.  
  243.     // all Reader positions, read lengths and memory locations must
  244.     // be aligned to this.
  245.     HRESULT Alignment(LONG* pl);
  246.  
  247.     HRESULT BeginFlush();
  248.     HRESULT EndFlush();
  249.  
  250.     LONG Alignment()
  251.     {
  252.         return m_pStream->Alignment();
  253.     };
  254.  
  255.     BOOL IsAligned(LONG l) {
  256.     if ((l & (Alignment() -1)) == 0) {
  257.         return TRUE;
  258.     } else {
  259.         return FALSE;
  260.     }
  261.     };
  262.  
  263.     BOOL IsAligned(LONGLONG ll) {
  264.     return IsAligned( (LONG) (ll & 0xffffffff));
  265.     };
  266.  
  267.     //  Accessor
  268.     HANDLE StopEvent() const { return m_evDone; }
  269. };
  270.  
  271. #endif // __ASYNCIO_H__
  272.